home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Development Tools & Languages / Dylan Related / Mindy-1.1 (sources only) / mindy-1.1 / libraries / dylan / coll.dylan < prev    next >
Encoding:
Text File  |  1994-08-23  |  32.8 KB  |  957 lines  |  [TEXT/ttxt]

  1. module: Dylan
  2. rcs-header: $Header: coll.dylan,v 1.20 94/08/22 15:25:12 nkramer Exp $
  3.  
  4. //======================================================================
  5. //
  6. // Copyright (c) 1994  Carnegie Mellon University
  7. // All rights reserved.
  8. // 
  9. // Use and copying of this software and preparation of derivative
  10. // works based on this software are permitted, including commercial
  11. // use, provided that the following conditions are observed:
  12. // 
  13. // 1. This copyright notice must be retained in full on any copies
  14. //    and on appropriate parts of any derivative works.
  15. // 2. Documentation (paper or online) accompanying any system that
  16. //    incorporates this software, or any part of it, must acknowledge
  17. //    the contribution of the Gwydion Project at Carnegie Mellon
  18. //    University.
  19. // 
  20. // This software is made available "as is".  Neither the authors nor
  21. // Carnegie Mellon University make any warranty about the software,
  22. // its performance, or its conformity to any specification.
  23. // 
  24. // Bug reports, questions, comments, and suggestions should be sent by
  25. // E-mail to the Internet address "gwydion-bugs@cs.cmu.edu".
  26. //
  27. //======================================================================
  28. //
  29. // This file contains the collection support code that isn't built in.
  30. //
  31.  
  32. define constant no_default :: <pair> = pair(#f, #f);
  33.  
  34.  
  35. // Collection routines
  36.  
  37. // We inherit the iteration protocol from the subclasses, which must define
  38. // it. 
  39. // define generic forward-iteration-protocol(collection);
  40.  
  41. // Element and element-setter will be implemented for arrays and vectors, but
  42. // we must define a default method for all collections.
  43. define method element(coll :: <collection>, key :: <object>,
  44.               #key default = no_default) => <object>;
  45.   let (init_state, limit, next_state, done?,
  46.        current_key, current_element) = forward-iteration-protocol(coll);
  47.   let test = key-test(coll);
  48.   block (return)
  49.     for (state = init_state then next_state(coll, state),
  50.      until done?(coll, state, limit))
  51.       if (test(current_key(coll, state), key))
  52.     return(current_element(coll, state));
  53.       end if;
  54.     finally
  55.       if (default == no_default)
  56.     error("No such element in %=: %=", coll, key);
  57.       else 
  58.     default;
  59.       end if;
  60.     end for;
  61.   end block;
  62. end method element;
  63.  
  64. define method element-setter (new_value, collection :: <mutable-collection>,
  65.                   key :: <object>)
  66.   let (init_state, limit, next_state, done?,
  67.        current_key, current_element,
  68.        current_element-setter) = forward-iteration-protocol(collection);
  69.   let test = key-test(collection);
  70.   block (return)
  71.     for (state = init_state then next_state(collection, state),
  72.      until done?(collection, state, limit))
  73.       if (test(current_key(collection, state), key))
  74.     current_element(collection, state) := new_value;
  75.     return();
  76.       end if;
  77.     end for;
  78.     error("No such element in %=: %=", collection, key);
  79.   end block;
  80. end method element-setter;
  81.  
  82. define method shallow-copy(collection :: <collection>) => <collection>;
  83.   map(identity, collection);
  84. end method shallow-copy;
  85.  
  86. define method as(cls :: limited(<class>, subclass-of: <collection>),
  87.          coll :: <collection>, #next next-method) => <object>;
  88.   case
  89.     instance?(coll, cls) =>
  90.       coll;
  91.     otherwise =>
  92.       map-as(cls, identity, coll);
  93.   end case;
  94. end method as;
  95.  
  96. // Note: This function depends upon a definition of \= for sequences, which
  97. // will be supplied later in this file.
  98. define method \=(a :: <collection>, b :: <collection>) => <object>;
  99.   let a-test = key-test(a);
  100.   let b-test = key-test(b);
  101.   
  102.   a-test == b-test
  103.     & key-sequence(a) = key-sequence(b) 
  104.     & every?(a-test, a, b);
  105. end method \=;
  106.  
  107. define method size(collection :: <collection>) => <integer>;
  108.   for (count from 0, elem in collection)
  109.   finally
  110.     count;
  111.   end for;
  112. end method size;
  113.  
  114. define method class-for-copy(collection :: <mutable-collection>) => <class>;
  115.   object-class(collection);
  116. end method class-for-copy;
  117.  
  118. define method empty?(collection :: <collection>) => <object>;
  119.   let (init, limit, next, done?) = forward-iteration-protocol(collection);
  120.   done?(collection, init, limit);
  121. end method empty?;
  122.  
  123. // Note: the map methods for arbitrary collections depend upon the iteration
  124. // protocol being defined for "rest args" (i.e. vectors).
  125. define method do(proc :: <function>, collection :: <collection>,
  126.          #rest more_collections)
  127.   let test1 = key-test(collection);
  128.   if (~ every?( method (c) test1 == key-test(c); end, more_collections ))
  129.     error("Can't do over collections with different key tests");
  130.   elseif (empty?(more_collections))
  131.     for (elem in collection) proc(elem) end for;
  132.   else
  133.     let keys = reduce(rcurry(intersection, test: test1),
  134.               key-sequence(collection),
  135.               map(key-sequence, more_collections));
  136.     for (key in keys)
  137.       apply(proc, collection[key],
  138.         map(rcurry(element, key), more_collections));
  139.     end for;
  140.   end if;
  141. end method do;
  142.  
  143. define method map(proc :: <function>, collection :: <collection>,
  144.           #rest more_collections) => <collection>;
  145.   apply(map-as, class-for-copy(collection), proc, collection,
  146.     more_collections);
  147. end method map;
  148.  
  149. // map-as must be given collections with the same key tests, but the
  150. // output collection apparently doesn't have to have the same key test
  151. // as its inputs.
  152.  
  153. define method map-as(cls :: <class>, proc :: <function>,
  154.              coll :: <collection>, #rest more_collections)
  155.     => <collection>;
  156.   let test = key-test (coll);
  157.   case
  158.     ~every? (method (c) key-test (c) == test end, more_collections) =>
  159.       error("Can't map over collections with different key tests");
  160.     size (coll) == #f
  161.       & every? (method (s) size (s) == #f end, more_collections) =>
  162.       error ("MAP-AS not applicable to unbounded collections");
  163.     empty? (more_collections) =>
  164.       let result = make (cls, size: size (coll));
  165.       let (init, limit, next, done?, curkey, curelt)
  166.         = forward-iteration-protocol (coll);
  167.       for (state = init then next (coll, state),
  168.        until done? (coll, state, limit))
  169.     result[curkey (coll, state)] := curelt (coll, state);
  170.       end for;
  171.       result;
  172.     otherwise => 
  173.       let keys = reduce (rcurry (intersection, test: test),
  174.              key-sequence (coll),
  175.              map (key-sequence, more_collections));
  176.       let result = make (cls, size: size (keys));
  177.       for (key in keys)
  178.     result[key] := apply (proc, element (coll, key),
  179.                   map (rcurry (element, key),
  180.                    more_collections));
  181.       end for;
  182.       result;
  183.   end case;
  184. end method map-as;
  185.  
  186. // map-into must be given collections with the same key tests, and the
  187. // destination must have the same key test as the sources.
  188.  
  189. define method map-into(destination :: <mutable-collection>, proc :: <function>,
  190.                coll :: <collection>, #rest more_collections)
  191.     => <collection>;
  192.   let test1 = key-test(coll);
  193.   if (~ every?( method (c) test1 == key-test(c); end, more_collections ))
  194.     error("Can't map over collections with different key tests");
  195.   elseif (~ (test1 == key-test(destination)))
  196.     error("Can't map into a collection with a different key test than its sources.");
  197.   elseif (empty?(more_collections))
  198.     let keys = intersection(key-sequence(coll), key-sequence(destination),
  199.                 test: test1);
  200.     for (key in keys)
  201.       destination[key] := proc(coll[key]);
  202.     end for;
  203.     destination;
  204.   else
  205.     let keys = intersection(reduce(rcurry(intersection, test: test1),
  206.                    key-sequence(coll),
  207.                    map(key-sequence, more_collections)),
  208.                 key-sequence(destination), test: test1);
  209.     for (key in keys)
  210.       destination[key] := apply(proc, coll[key],
  211.                 map(rcurry(element, key), more_collections));
  212.     end for;
  213.     destination;
  214.   end if;
  215. end method map-into;
  216.  
  217. define method any?(proc :: <function>, collection :: <collection>,
  218.            #rest more_collections) => <object>;
  219.   let test1 = key-test(collection);
  220.   if (~ every?( method (c) test1 == key-test(c); end, more_collections ))
  221.     error("Can't do collection alignment over collections with different key tests");
  222.   end if;
  223.  
  224.   block (return)
  225.     if (empty?(more_collections))
  226.       for (elem in collection)
  227.     let result = proc(elem);
  228.     if (result) return(result) end if;
  229.       end for;
  230.     else 
  231.       let keys = reduce(rcurry(intersection, test: test1),
  232.             key-sequence(collection),
  233.             map(key-sequence, more_collections));
  234.       for (key in keys)
  235.     let result = apply(proc, collection[key],
  236.                map(rcurry(element, key), more_collections));
  237.     if (result) return(result) end if;
  238.       end for;
  239.     end if;
  240.     #f;
  241.   end block;
  242. end method any?;
  243.  
  244. define method every?(proc :: <function>, collection :: <collection>,
  245.            #rest more_collections) => <object>;
  246.   let test1 = key-test(collection);
  247.   if (~ every?( method (c) test1 == key-test(c); end, more_collections ))
  248.     error("Can't do collection alignment over collections with different key tests");
  249.   end if;
  250.  
  251.   block (return)
  252.     if (empty?(more_collections))
  253.       for (elem in collection)
  254.     unless (proc(elem)) return(#f) end unless;
  255.       end for;
  256.     else
  257.       let keys = reduce(rcurry(intersection, test: test1),
  258.             key-sequence(collection),
  259.             map(key-sequence, more_collections));
  260.       for (key in keys)
  261.     let result = apply(proc, collection[key],
  262.                map(rcurry(element, key), more_collections));
  263.     unless (result) return(#f) end unless;
  264.       end for;
  265.     end if;
  266.     #t;
  267.   end block;
  268. end method every?;
  269.  
  270. define method reduce(proc :: <function>, init_val, collection :: <collection>)
  271.   for (value = init_val then proc(value, elem),
  272.        elem in collection)
  273.   finally value;
  274.   end for;
  275. end method reduce;
  276.  
  277. define method reduce1(proc :: <function>, collection :: <collection>)
  278.   let (init_state, limit, next_state, done?,
  279.        current_key, current_element) = forward-iteration-protocol(collection);
  280.   if (done?(collection, init_state, limit)) // empty collection
  281.     error("Reduce1 not defined for empty collections.");
  282.   else 
  283.     for (// The computation of "value" must precede the computation of "state",
  284.      // since "next_state" may invalidate the current state.
  285.      value = current_element(collection, init_state)
  286.        then proc(value, current_element(collection, state)),
  287.      state = next_state(collection, init_state)
  288.        then next_state(collection, state),
  289.      until done?(collection, state, limit))
  290.     finally value;
  291.     end for;
  292.   end if;
  293. end method reduce1;
  294.  
  295. define method member?(value :: <object>, collection :: <collection>,
  296.               #key test = \==) => <object>;
  297.   block (return)
  298.     for (element in collection)
  299.       if (test(value, element)) return(#t) end if;
  300.     end for;
  301.   end block;
  302. end method member?;
  303.  
  304. define method replace-elements!(collection :: <mutable-collection>,
  305.                 predicate :: <function>,
  306.                 new_value_fn :: <function>,
  307.                 #key count: count) => <mutable-collection>;
  308.   let (init_state, limit, next_state, done?,
  309.        current_key, current_element,
  310.        current_element-setter) = forward-iteration-protocol(collection);
  311.   for (state = init_state then next_state(collection, state),
  312.        until done?(collection, state, limit) | count == 0)
  313.     let this_element = current_element(collection, state);
  314.     if (predicate(this_element))
  315.       current_element(collection, state) := new_value_fn(this_element);
  316.       if (count) count := count - 1 end if;
  317.     end if;
  318.   end for;
  319.   collection;
  320. end method replace-elements!;
  321.  
  322. define method fill!(collection :: <mutable-collection>, value :: <object>,
  323.             #key start: first, end: last) => <mutable-collection>;
  324.   // ignore keywords, since they aren't meaningful for arbitrary collections.
  325.   let (init_state, limit, next_state, done?,
  326.        current_key, current_element,
  327.        current_element-setter) = forward-iteration-protocol(collection);
  328.   for (state = init_state then next_state(collection, state),
  329.        until done?(collection, state, limit))
  330.     current_element(collection, state) := value;
  331.   end for;
  332.   collection;
  333. end method fill!;
  334.  
  335. define method find-key(collection :: <collection>, proc :: <function>,
  336.                #key skip, failure = #f)
  337.   let (init_state, limit, next_state, done?,
  338.        current_key, current_element) = forward-iteration-protocol(collection);
  339.   block (return)
  340.     for (state = init_state then next_state(collection, state),
  341.      until done?(collection, state, limit))
  342.       if (proc(current_element(collection, state)))
  343.     if (skip & skip > 0)
  344.       skip := skip - 1;
  345.     else
  346.       return(current_key(collection, state));
  347.     end if;
  348.       end if;
  349.     finally failure
  350.     end for;
  351.   end block;
  352. end method find-key;
  353.  
  354. define method key-sequence(collection :: <collection>) => <collection>;
  355.   let (init_state, limit, next_state, done?,
  356.        current_key, current_element) = forward-iteration-protocol(collection);
  357.   let result = make(<vector>, size: size(collection));
  358.   for (index from 0,
  359.        state = init_state then next_state(collection, state),
  360.        until done?(collection, state, limit))
  361.     result[index] := current_key(collection, state);
  362.   end for;
  363.   result;
  364. end method key-sequence;
  365.  
  366. // Sequence routines.
  367.  
  368. define method element(sequence :: <sequence>, key :: <integer>,
  369.               #key default = no_default) => <object>;
  370.   block (return)
  371.     for (this_key from 0, elem in sequence)
  372.       if (this_key == key) return(elem) end if;
  373.     finally
  374.       if (default == no_default)
  375.     error("No such element in %=: %=", sequence, key);
  376.       else 
  377.     default;
  378.       end if;
  379.     end for;
  380.   end block;
  381. end method element;
  382.  
  383. define method element-setter (new_value, sequence :: <mutable-sequence>,
  384.                   key :: <integer>)
  385.   let (init_state, limit, next_state, done?,
  386.        current_key, current_element,
  387.        current_element-setter) = forward-iteration-protocol(sequence);
  388.   block (return)
  389.     for (this_key from 0,
  390.      state = init_state then next_state(sequence, state),
  391.      until done?(sequence, state, limit))
  392.       if (this_key == key)
  393.     current_element(sequence, state) := new_value;
  394.     return();
  395.       end if;
  396.     end for;
  397.     error("No such element in %=: %=", sequence, key);
  398.   end block;
  399. end method element-setter;
  400.  
  401. define method \=(a :: <sequence>, b :: <sequence>) => <object>;
  402.   let (a_init, a_limit, a_next, a_done?, a_key, a_elem)
  403.     = forward-iteration-protocol(a);
  404.   let (b_init, b_limit, b_next, b_done?, b_key, b_elem)
  405.     = forward-iteration-protocol(b);
  406.   block (return)
  407.     for (a_state = a_init then a_next(a, a_state),
  408.      b_state = b_init then b_next(b, b_state),
  409.      until a_done?(a, a_state, a_limit) | b_done?(b, b_state, b_limit))
  410.       if (a_elem(a, a_state) ~= b_elem(b, b_state))
  411.     return(#f);
  412.       end if;
  413.     finally
  414.       if (~a_done?(a, a_state, a_limit) | ~b_done?(b, b_state, b_limit))
  415.     return(#f);
  416.       end if;
  417.     end for;
  418.     #t;
  419.   end block;
  420. end method \=;
  421.  
  422. define method key-test (sequence :: <sequence>) => test :: <function>;
  423.   \==;            // Return the function == (id?)
  424. end method key-test;
  425.  
  426. define method key-sequence(sequence :: <sequence>) => <range>;
  427.   let s = size (sequence);
  428.   if (s)
  429.     range (from: 0, below: s);
  430.   else
  431.     range (from: 0);
  432.   end if;
  433. end method key-sequence;
  434.  
  435. define constant aux_map_as =
  436.   method (cls :: <class>, proc :: <function>, #rest seqs)
  437.     let finite-lengths = choose (identity, map (size, seqs));
  438.     let length = apply(min, finite-lengths);
  439.     let result = make(cls, size: length);
  440.     let (init, limit, next, done?, key, elem, elem-setter)
  441.       = forward-iteration-protocol(result);
  442.     let seq_count = size(seqs);
  443.     let states = make(<vector>, size: seq_count);
  444.     let vals = make(<vector>, size: seq_count);
  445.     let nexts = make(<vector>, size: seq_count);
  446.     let elems = make(<vector>, size: seq_count);
  447.  
  448.     for (pos from 0, seq in seqs)
  449.       let (init, limit, next, done?, key, elem)
  450.     = forward-iteration-protocol(seq);
  451.       states[pos] := init;
  452.       nexts[pos] := next;
  453.       elems[pos] := elem;
  454.     end for;
  455.  
  456.     for (state = init then next(result, state),
  457.      until done?(result, state, limit))
  458.       for (i from 0 below seq_count)
  459.     let (this_seq, this_state) = values(seqs[i], states[i]);
  460.     vals[i] := elems[i](this_seq, this_state);
  461.     states[i] := nexts[i](this_seq, this_state);
  462.       end for;
  463.       elem(result, state) := apply(proc, vals);
  464.     end for;
  465.  
  466.     result;
  467.   end method;
  468.  
  469. define method map-as(cls :: <class>, proc :: <function>,
  470.              sequence :: <sequence>,
  471.              #next next-method, #rest more_sequences)
  472.   case
  473.     size (sequence) == #f
  474.       & every? (method (s) size (s) == #f end, more_sequences) =>
  475.       error ("MAP-AS not applicable to unbounded sequences");
  476.     empty?(more_sequences) =>
  477.       let result = make(cls, size: size(sequence));
  478.       let (res_init, res_limit, res_next, res_done?, res_key, res_elem,
  479.        res_elem-setter) = forward-iteration-protocol(result);
  480.       for (element in sequence,
  481.        res_state = res_init then res_next(result, res_state))
  482.     res_elem(result, res_state) := proc(element);
  483.       end for;
  484.       result;
  485.     every?(rcurry(instance?, <sequence>), more_sequences) =>
  486.       apply(aux_map_as, cls, proc, sequence, more_sequences);
  487.     otherwise =>
  488.       next-method();
  489.   end case;
  490. end method map-as;
  491.  
  492. define method map-into(destination :: <mutable-sequence>, proc :: <function>,
  493.                sequence :: <sequence>,
  494.                #next next-method, #rest more_sequences)
  495.   if (empty?(more_sequences))
  496.     let (res_init, res_limit, res_next, res_done?, res_key, res_elem,
  497.      res_elem-setter) = forward-iteration-protocol(destination);
  498.     for (element in sequence,
  499.      res_state = res_init then res_next(destination, res_state),
  500.      until res_done?(destination, res_state, res_limit))
  501.       res_elem(destination, res_state) := proc(element);
  502.     end for;
  503.     destination;
  504.   else
  505.     next-method();
  506.   end if;
  507. end method map-into;
  508.  
  509. define method fill!(sequence :: <mutable-sequence>, value :: <object>,
  510.             #next next-method,
  511.             #key start: first = 0, end: last) => <mutable-sequence>;
  512.   // The "collection" method will likely be faster if there are no keywrds.
  513.   if (first = 0 & ~last) next-method() end if;
  514.     
  515.   let (init_state, limit, next_state, done?,
  516.        current_key, current_element,
  517.        current_element-setter) = forward-iteration-protocol(sequence);
  518.   for (state = init_state then next_state(sequence, state),
  519.        index from 0 below first,
  520.        until done?(sequence, state, limit))
  521.   finally
  522.     if (last)
  523.       for (state = state then next_state(sequence, state),
  524.        index from index below last,
  525.        until done?(sequence, state, limit))
  526.     current_element(sequence, state) := value;
  527.       end for;
  528.     else
  529.       for (state = state then next_state(sequence, state),
  530.        until done?(sequence, state, limit))
  531.     current_element(sequence, state) := value;
  532.       end for;
  533.     end if;
  534.   end for;
  535.   sequence;
  536. end method fill!;
  537.  
  538. define method find-key(sequence :: <sequence>, proc :: <function>,
  539.                #key skip, failure = #f)
  540.   let (init_state, limit, next_state, done?,
  541.        current_key, current_element) = forward-iteration-protocol(sequence);
  542.   block (return)
  543.     for (elem in sequence,
  544.      key from 0)
  545.       if (proc(elem))
  546.     if (skip & skip > 0)
  547.       skip := skip - 1;
  548.     else
  549.       return(key);
  550.     end if;
  551.       end if;
  552.     finally failure
  553.     end for;
  554.   end block;
  555. end method find-key;
  556.  
  557. define method add(sequence :: <sequence>, new_element) => <sequence>;
  558.   let old_size = size(sequence);
  559.   let result = make(class-for-copy(sequence), size: old_size + 1);
  560.   map-into(result, identity, sequence);
  561.   result[old_size] := new_element;
  562.   result;
  563. end method add;
  564.  
  565. define method add!(sequence :: <sequence>, new_element) => <sequence>;
  566.   add(sequence, new_element);
  567. end method add!;
  568.  
  569. define method add-new(sequence :: <sequence>, new_element,
  570.               #key test = \==) => <sequence>;
  571.   if (any?(rcurry(test, new_element), sequence))
  572.     sequence;
  573.   else
  574.     add(sequence, new_element);
  575.   end if;
  576. end method add-new;
  577.  
  578. define method add-new!(sequence :: <sequence>, new_element,
  579.               #key test = \==) => <sequence>;
  580.   if (any?(rcurry(test, new_element), sequence))
  581.     sequence;
  582.   else
  583.     add!(sequence, new_element);
  584.   end if;
  585. end method add-new!;
  586.  
  587. define method remove(sequence :: <sequence>, value,
  588.              #key test = \==, count) => <sequence>;
  589.   for (result = #() then if (count = 0)
  590.                pair(elem, result);
  591.              elseif (~test(elem, value))
  592.                if (count) count := count - 1 end if;
  593.                pair(elem, result);
  594.              else result
  595.              end if,
  596.        elem in sequence)
  597.   finally
  598.     as(class-for-copy(sequence), reverse!(result));
  599.   end for;
  600. end remove;
  601.  
  602. define method remove!(sequence :: <sequence>, value,
  603.               #key test = \==, count: count) => <sequence>;
  604.   remove(sequence, value, test: test, count: count);
  605. end method remove!;
  606.  
  607. define generic size-setter(length, collection);
  608.  
  609. define method shrink!(sequence :: <sequence>, length) => <sequence>;
  610.   if (applicable-method?(size-setter, length, sequence))
  611.     copy-sequence(sequence, end: length);
  612.   else
  613.     size(sequence) := length;
  614.   end if;
  615. end method;
  616.  
  617. define method remove! (sequence :: <mutable-sequence>, value,
  618.                #key test = \==, count: count) => <sequence>;
  619.   let (init_state, limit, next_state, done?, current_key,
  620.        current_element, current_element-setter,
  621.        copy_state) = forward-iteration-protocol(sequence);
  622.   local method replace (dest_state, src_state,
  623.             replaced :: <integer>, length :: <integer>)
  624.       case
  625.         done?(sequence, src_state, limit) =>
  626.           shrink!(sequence, length);
  627.         replaced = count =>
  628.           for (dest_state = dest_state
  629.              then next_state(sequence, dest_state),
  630.            src_state = src_state then next_state(sequence, src_state),
  631.            length from length,
  632.            until done?(sequence, src_state, limit))
  633.         current_element(sequence, dest_state)
  634.           := current_element(sequence, src_state);
  635.           finally
  636.         shrink!(sequence, length);
  637.           end for;
  638.         test(current_element(sequence, src_state), value) =>
  639.           replace(dest_state, next_state(sequence, src_state),
  640.               replaced + 1, length);
  641.         otherwise =>
  642.           current_element(sequence, dest_state)
  643.             := current_element(sequence, src_state);
  644.           replace(next_state(sequence, dest_state),
  645.               next_state(sequence, src_state), replaced, length + 1);
  646.       end case;
  647.     end method replace;
  648.   if (count = 0)
  649.     sequence;
  650.   else 
  651.     block (return)
  652.       for (state = init_state then next_state(sequence, state),
  653.        length from 0,
  654.        until done?(sequence, state, limit))
  655.     if (test(current_element(sequence, state), value))
  656.       return(replace(copy_state(sequence, state),
  657.              next_state(sequence, state), 1, length));
  658.     end if;
  659.       finally
  660.     sequence;
  661.       end for;
  662.     end block;
  663.   end if;
  664. end method remove!;
  665.  
  666. define method choose(predicate :: <function>,
  667.              sequence :: <sequence>) => <sequence>;
  668.   for (result = #() then if (predicate(elem)) pair(elem, result)
  669.              else result
  670.              end if,
  671.        elem in sequence)
  672.   finally as(class-for-copy(sequence), reverse!(result));
  673.   end for;
  674. end choose;
  675.  
  676. define method choose-by(predicate :: <function>, test_seq :: <sequence>,
  677.             value_seq :: <sequence>) => <sequence>;
  678.   for (result = #() then if (predicate(test_elem)) pair(value_elem, result)
  679.              else result
  680.              end if,
  681.        value_elem in value_seq, test_elem in test_seq)
  682.   finally as(class-for-copy(value_seq), reverse!(result));
  683.   end for;
  684. end method;
  685.  
  686. define method intersection(sequence1 :: <sequence>, sequence2 :: <sequence>,
  687.                #key test = \==) => <sequence>;
  688.   choose(method (item) member?(item, sequence2, test: test) end method,
  689.      sequence1);
  690. end method intersection;
  691.  
  692. define method difference(sequence1 :: <sequence>, sequence2 :: <sequence>,
  693.              #key test = \==) => <sequence>;
  694.   choose(method (item) ~member?(item, sequence2, test: test) end method,
  695.      sequence1);
  696. end method difference;
  697.  
  698. define method union(sequence1 :: <sequence>, sequence2 :: <sequence>,
  699.             #key test = \==) => <sequence>;
  700.   concatenate(sequence1, difference(sequence2, sequence1,
  701.                     test: method(a, b) test(b,a) end method));
  702. end method union;
  703.  
  704. define method remove-duplicates(sequence :: <sequence>,
  705.                 #key test = \==) => <sequence>;
  706.   local method true_test(a, b) test(b, a) end method;
  707.   for (result = #() then if (~member?(element, result, test: true_test))
  708.                pair(element, result);
  709.              else result
  710.              end if,
  711.        element in sequence)
  712.   finally as(class-for-copy(sequence), reverse!(result));
  713.   end for;
  714. end method remove-duplicates;
  715.  
  716. define method remove-duplicates!(sequence :: <sequence>,
  717.                  #key test = \==) => <sequence>;
  718.   remove-duplicates(sequence, test: test);
  719. end method remove-duplicates!;
  720.  
  721. define method copy-sequence(sequence :: <sequence>,
  722.                 #key start: first = 0, end: last) => <sequence>;
  723.   let last = if (last) min(last, size(sequence)) else size(sequence) end if;
  724.   let start = min(first, last);
  725.   let sz = if (start <= last) 
  726.          last - start;
  727.        else
  728.          error("End: (%=) is smaller than start: (%=)", last, start);
  729.        end if;
  730.   let result = make(class-for-copy(sequence), size: sz);
  731.   let (init_state, limit, next_state, done?,
  732.        current_key, current_element) = forward-iteration-protocol(sequence);
  733.  
  734.   for (index from 0 below start,
  735.        state = init_state then next_state(sequence, state))
  736.   finally
  737.     let (res_init, res_limit, res_next, res_done?, res_key,
  738.      res_elem, res_elem-setter) = forward-iteration-protocol(result);
  739.     for (index from index below last,
  740.      state = state then next_state(sequence, state),
  741.      res_state = res_init then res_next(result, res_state))
  742.       res_elem(result, res_state) := current_element(sequence, state);
  743.     end for;
  744.   end for;
  745.   result;
  746. end method copy-sequence;
  747.  
  748. define method concatenate-as(cls :: <class>, sequence :: <sequence>,
  749.                  #rest more_sequences) => <sequence>;
  750.   if (size (sequence) == #f
  751.     | any? (method (s) size (s) == #f end, more_sequences))
  752.     error ("CONCATENATE-AS not applicable to unbounded sequences");
  753.   end if;
  754.   let length = reduce(method (int, seq) int + size(seq) end method,
  755.               size(sequence), more_sequences);
  756.   let result = make(cls, size: length);
  757.   let (init_state, limit, next_state, done?, current_key, current_element,
  758.        current_element-setter) = forward-iteration-protocol(result);
  759.   local method do_copy(state, seq :: <sequence>) // :: state
  760.       for (state = state then next_state(result, state),
  761.            elem in seq)
  762.         current_element(result, state) := elem;
  763.       finally state;
  764.       end for;
  765.     end method do_copy;
  766.   reduce(do_copy, do_copy(init_state, sequence), more_sequences);
  767.   result;
  768. end method concatenate-as;
  769.  
  770. define method concatenate(sequence :: <sequence>,
  771.               #rest more_sequences) => <sequence>;
  772.   apply(concatenate-as, class-for-copy(sequence), sequence, more_sequences);
  773. end method concatenate;
  774.  
  775. define method replace-subsequence!(sequence :: <mutable-sequence>,
  776.                    insert_sequence :: <sequence>,
  777.                    #key start: first = 0,
  778.                         end: last) => <sequence>;
  779.   let last = last | size(sequence);
  780.   concatenate(copy-sequence(sequence, start: 0, end: first), insert_sequence,
  781.           copy-sequence(sequence, start: last));
  782. end method replace-subsequence!;
  783.  
  784. define method reverse(sequence :: <sequence>) => <sequence>;
  785.   let result = make(class-for-copy(sequence), size: size(sequence));
  786.   let (res-state, res-limit, res-next, res-done?, res-key, res-elem,
  787.        res-elem-setter) = forward-iteration-protocol(result);
  788.   let (source-state, source-limit, source-next, source-done?, source-key,
  789.        source-elem) = forward-iteration-protocol(sequence);
  790.   local method reverse1(res-state, source-state) // :: res-state
  791.       if (source-done?(sequence, source-state, source-limit))
  792.         res-state
  793.       else 
  794.         let elem = source-elem(sequence, source-state);
  795.         let new-res-state =
  796.           reverse1(res-state, source-next(sequence, source-state));
  797.         res-elem(result, new-res-state) := elem;
  798.         res-next(result, new-res-state);
  799.       end if;
  800.     end method reverse1;
  801.   reverse1(res-state, source-state);
  802.   result;
  803. end method;
  804.  
  805. define method reverse!(sequence :: <sequence>) => <sequence>;
  806.   reverse(sequence);
  807. end method reverse!;
  808.  
  809. define method first(sequence :: <sequence>, #rest keys, #key default)
  810.   apply(element, sequence, 0, keys);
  811. end method first;
  812.  
  813. define method second(sequence :: <sequence>, #rest keys, #key default)
  814.   apply(element, sequence, 1, keys);
  815. end method second;
  816.  
  817. define method third(sequence :: <sequence>, #rest keys, #key default)
  818.   apply(element, sequence, 2, keys);
  819. end method third;
  820.  
  821. define method first-setter(value, sequence :: <sequence>)
  822.   sequence[0] := value;
  823. end method first-setter;
  824.  
  825. define method second-setter(value, sequence :: <sequence>)
  826.   sequence[1] := value;
  827. end method second-setter;
  828.  
  829. define method third-setter(value, sequence :: <sequence>)
  830.   sequence[2] := value;
  831. end method third-setter;
  832.  
  833. define method last(sequence :: <sequence>, #rest keys, #key default)
  834.   apply(element, sequence, size(sequence) - 1, keys);
  835. end method last;
  836.     
  837. define method last-setter(value, sequence :: <sequence>)
  838.   sequence[size(sequence) - 1] := value;
  839. end method last-setter;
  840.     
  841. define method subsequence-position(big :: <sequence>, pattern :: <sequence>,
  842.                    #key test = \==, count = 1)
  843.  
  844.   let (init-state, limit, next-state, done?,
  845.        current-key, current-element,
  846.        current-element-setter, copy-state) = forward-iteration-protocol(big);
  847.   let (pat-init-state, pat-limit, pat-next-state,
  848.        pat-done?, pat-current-key, pat-current-element,
  849.        pat-current-element-setter,
  850.        pat-copy-state) = forward-iteration-protocol(pattern);
  851.   
  852.   if (empty?(pattern))
  853.     0
  854.   else
  855.     local method search(index, index-state, big-state, pat-state, count)
  856.         case
  857.           pat-done?(pattern, pat-state, pat-limit) =>
  858.         // End of pattern -- We found one.
  859.         if (count = 1)
  860.           index
  861.         else
  862.           let next = next-state(big, index-state);
  863.           search(index + 1, next, copy-state(big, next),
  864.              pat-copy-state(pattern, pat-init-state), count - 1);
  865.         end if;
  866.           done?(big, big-state, limit) =>
  867.         // End of big sequence -- it's not here.
  868.         #f;
  869.           test(current-element(big, big-state),
  870.            pat-current-element(pattern, pat-state)) =>
  871.         // They match -- try one more.
  872.         search(index, index-state, next-state(big, big-state),
  873.                pat-next-state(pattern, pat-state), count);
  874.           otherwise =>
  875.         // Don't match -- try one further along.
  876.         let next = next-state(big, index-state);
  877.             search(index + 1, next, next & copy-state(big, next),
  878.                pat-copy-state(pattern, pat-init-state), count);
  879.         end case;
  880.       end method search;
  881.     search(0, copy-state(big, init-state), copy-state(big, init-state),
  882.        pat-copy-state(pattern, pat-init-state), count);
  883.   end if;
  884. end method subsequence-position;
  885.  
  886. // Stretchy collections -- se Design Note #27
  887. define abstract class <stretchy-collection> (<collection>) end class;
  888.  
  889. define method map-into(destination :: <stretchy-collection>,
  890.                proc :: <function>, coll :: <collection>,
  891.                #rest more_collections) => <stretchy-collection>;
  892.   let test1 = key-test(coll);
  893.   if (~instance?(destination, <mutable-collection>))
  894.     error("%= is not a mutable collection.", destination);
  895.   elseif (~ every?( method (c) test1 == key-test(c); end, more_collections ))
  896.     error("Can't map over collections with a different key tests");
  897.   elseif (~ (test1 == key-test(destination)))
  898.     error("Can't map into a collection with a different key test than its sources.");
  899.   elseif (empty?(more_collections))
  900.     for (key in key-sequence(destination))
  901.       destination[key] := proc(coll[key]);
  902.     end for;
  903.   else
  904.     let keys = reduce(rcurry(intersection, test: test1), key-sequence(coll),
  905.               map(key-sequence, more_collections));
  906.     for (key in keys)
  907.       destination[key] := apply(proc, coll[key],
  908.                 map(rcurry(element, key), more_collections));
  909.     end for;
  910.   end if;
  911.   destination;
  912. end method map-into;
  913.  
  914. // We must define this method or the above method will be ambiguous with the
  915. // "<mutable-sequence>" method.
  916. define method map-into(destination :: <stretchy-collection>,
  917.                proc :: <function>, sequence :: <sequence>,
  918.                #rest more_sequences)
  919.   let test1 = key-test(sequence);
  920.   if (~instance?(destination, <mutable-collection>))
  921.     error("%= is not a mutable collection.", destination);
  922.   elseif (~ every?( method (c) test1 == key-test(c); end, more_sequences ))
  923.     error("Can't map over collections with a different key tests");
  924.   elseif (~ (test1 == key-test(destination)))
  925.     error("Can't map into a collection with a different key test than its sources.");
  926.   elseif (empty?(more_sequences))
  927.     let (res_init, res_limit, res_next, res_done?, res_key, res_elem,
  928.      res_elem-setter) = forward-iteration-protocol(destination);
  929.     let (src_init, src_limit, src_next, src_done?, src_key, src_elem)
  930.       = forward-iteration-protocol(sequence);
  931.     for (key from 0,
  932.      src_state = src_init then src_next(sequence, src_state),
  933.      res_state = res_init then res_next(destination, res_state),
  934.      until src_done?(sequence, src_state, src_limit) |
  935.        res_done?(destination, res_state, res_limit))
  936.       res_elem(destination, res_state) := proc(src_elem(sequence, src_state));
  937.     finally
  938.       for (key from key,
  939.        src_state = src_state then src_next(sequence, src_state),
  940.        until src_done?(sequence, src_state, src_limit))
  941.     destination[key] := proc(src_elem(sequence, src_state));
  942.       end for;
  943.     end for;
  944.     destination;
  945.   else
  946.     // Duplicated code from "<collection>" method, to avoid next-method
  947.     // ambiguity. 
  948.     let keys = reduce(rcurry(intersection, test: test1), key-sequence(sequence),
  949.               map(key-sequence, more_sequences));
  950.     for (key in keys)
  951.       destination[key] := apply(proc, sequence[key],
  952.                 map(rcurry(element, key), more_sequences));
  953.     end for;
  954.     destination;
  955.   end if;
  956. end method map-into;
  957.